#ifndef FILEUTIL
#define FILEUTIL

#include <iostream>
#include <string>
#include <sys/types.h>
#include <experimental/filesystem>
#include <sys/stat.h>
#include <unistd.h>
#include <fstream>
#include <sstream>
#include "bundle.h"

// typedef ;
namespace bucai
{
    namespace fs = std::experimental::filesystem;
    class fileUtil
    {
    private:
        std::string _filename;

        struct stat _stat; // 系统文件接口 Linux和win平台都有内置

    public:
        fileUtil(const std::string &name) : _filename(name)
        {
            stat(_filename.c_str(), &_stat);
        }
        size_t FileSize()
        {
            // return fs::file_size(_p1);
            return _stat.st_size;
        }
        time_t LastATime()
        {
            return _stat.st_atime; // 系统文件接口 Linux和win平台都有内置
        }
        time_t LastMTime()
        {
            // return fs::last_write_time(_p1); //C++17文件类
            return _stat.st_mtime;
        }
        std::string FileName()
        {

            int num = _filename.find_last_of('/');
            std::string name = _filename.substr(num + 1);
            return name;
        }
        bool GetPosLen(std::string *content, size_t pos, size_t len)
        { // 读取文件pos位置，len长度
            std::ifstream ifs;
            ifs.open(_filename, std::ios::binary);
            ifs.seekg(pos, std::ios::beg);

            if (FileSize() == 0)
            {
                std::cout << "file not exist" << std::endl;
                ifs.close();
                return false;
            }

            content->resize(len);
            ifs.read(&(*content)[0], len);

            ifs.close();
            return true;
        }
        bool GetContent(std::string *content)
        { // 读取文件全部内容
            GetPosLen(content, 0, FileSize());
            return true;
        }
        bool SetContent(const std::string &content)
        { // 写入文件
            std::ofstream ofs;
            ofs.open(_filename, std::ios::binary); // 是覆盖
            ofs.write(&content[0], content.size());
            ofs.close();
            return true;
        }
        bool Compress(const std::string &packname) // 压缩文件， 传入压缩后的名称
        {
            // std::ifstream ifs;
            // std::string ifilename = _filename;
            // std::string ofilename = packname;
            // ifs.open(ifilename, std::ios::binary);

            // ifs.seekg(0, std::ios::end);
            // auto sz = ifs.tellg();
            // ifs.seekg(0, std::ios::beg);

            // std::string s1;
            // s1.resize(sz);

            // ifs.read(&s1[0], sz);
            // std::string zip = bundle::pack(bundle::LZIP, s1); // 压缩数据
            // ifs.close();

            // std::ofstream ofs;
            // ofs.open(ofilename, std::ios::binary);
            // ofs.write(&zip[0], zip.size()); // 把压缩后的数据，写入压缩文件中
            // ofs.close();
            // return true;
            std::string body;
            if (this->GetContent(&body) == false)
            {
                std::cout << "compress get file content failed!\n";
                return false;
            }
            // 2. 对数据进行压缩
            std::string packed = bundle::pack(bundle::LZIP, body);
            // 3. 将压缩的数据存储到压缩包文件中
            bucai::fileUtil fu(packname);
            if (fu.SetContent(packed) == false)
            {
                std::cout << "compress write packed data failed!\n";
                return false;
            }
            return true;
        }

        bool UnCompress(const std::string &filename) // 解压缩文件 传入解压缩后的名称(路径)
        {
            // 打开待解压文件
            std::ifstream ifs;
            std::string ifilename = _filename;
            std::string ofilename = filename;

            ifs.open(ifilename, std::ios::binary);
            ifs.seekg(0, std::ios::end);
            size_t sz = ifs.tellg(); // 计算出文件大小
            ifs.seekg(0, std::ios::beg);

            std::string s1; // 创建存储带解压文件内容
            s1.resize(sz);  // 重定义字符串大小，避免空间浪费
            ifs.read(&s1[0], sz);

            std::string unzip = bundle::unpack(s1); // 解压内容写入新字符串中。

            ifs.close();

            std::ofstream ofs; // 打开解压存储文件
            ofs.open(ofilename, std::ios::binary);
            ofs.write(&unzip[0], unzip.size()); // 把解压内容写入文件中
            ofs.close();
            return true;
        }
        // bool UnCompress(const std::string &output_path)
        // {
        //     // 1. 检查输入文件是否存在
        //     if (!this->Exists())
        //     {
        //         std::cerr << "[ERROR] Input file not found: " << _filename << std::endl;
        //         return false;
        //     }

        //     // 2. 尝试打开输入文件
        //     std::ifstream ifs(_filename, std::ios::binary);
        //     if (!ifs)
        //     {
        //         std::cerr << "[ERROR] Failed to open input file: " << _filename
        //                   << " | Error: " << strerror(errno) << std::endl;
        //         return false;
        //     }

        //     // 3. 读取文件内容
        //     std::string compressed_data;
        //     try
        //     {
        //         ifs.seekg(0, std::ios::end);
        //         size_t file_size = ifs.tellg();
        //         ifs.seekg(0, std::ios::beg);

        //         compressed_data.resize(file_size);
        //         ifs.read(compressed_data.data(), file_size);

        //         if (!ifs)
        //         {
        //             std::cerr << "[ERROR] Failed to read file: " << _filename << std::endl;
        //             return false;
        //         }
        //     }
        //     catch (const std::exception &e)
        //     {
        //         std::cerr << "[EXCEPTION] File read error: " << e.what() << std::endl;
        //         return false;
        //     }

        //     // 4. 解压数据
        //     std::string uncompressed_data;
        //     try
        //     {
        //         uncompressed_data = bundle::unpack(compressed_data); // 核心解压调用
        //     }
        //     catch (const std::exception &e)
        //     {
        //         std::cerr << "[EXCEPTION] Unpack failed: " << e.what() << std::endl;
        //         return false;
        //     }

        //     // 5. 确保输出目录存在
        //     fs::path out_path(output_path);
        //     try
        //     {
        //         fs::create_directories(out_path.parent_path());
        //     }
        //     catch (...)
        //     {
        //         std::cerr << "[ERROR] Failed to create output directory" << std::endl;
        //         return false;
        //     }

        //     // 6. 写入解压后文件
        //     std::ofstream ofs(output_path, std::ios::binary);
        //     if (!ofs)
        //     {
        //         std::cerr << "[ERROR] Failed to open output file: " << output_path
        //                   << " | Error: " << strerror(errno) << std::endl;
        //         return false;
        //     }

        //     ofs.write(uncompressed_data.data(), uncompressed_data.size());
        //     if (!ofs)
        //     {
        //         std::cerr << "[ERROR] Failed to write output file" << std::endl;
        //         return false;
        //     }

        //     std::cout << "[SUCCESS] Uncompressed " << _filename
        //               << " to " << output_path << std::endl;
        //     return true;
        // }
        bool Exists()
        {
            return fs::exists(_filename);
        }
        bool CreateDirectory()
        {
            if (this->Exists())
                return true;
            return fs::create_directory(_filename);
        }
        bool ScanDirectory(std::vector<std::string> *arry)
        {
            for (auto &p : fs::directory_iterator(_filename))
            {
                if (fs::is_directory(p) == true)
                {
                    continue;
                }
                // relative_path 带有路径的文件名
                arry->push_back(fs::path(p).relative_path().string());
            }
            return true;
        }
        bool Remove()
        {
            if (this->Exists() == false)
            {
                return true;
            }
            remove(_filename.c_str());
            return true;
        }
    };
}; // namespace bucai

#endif